package com.tanhua.dubbo.server.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.tanhua.dubbo.server.enums.IdType;
import com.tanhua.dubbo.server.pojo.FollowUser;
import com.tanhua.dubbo.server.pojo.Video;
import com.tanhua.dubbo.server.service.IdService;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;

/**
 * @author LOVE
 */

@Service(version = "1")
public class VideoApiImpl implements VideoApi {

    @Autowired
    private IdService idService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplatel;

    /**
     * 按 ID 查询视频
     *
     * @param videoId 小视频id
     * @return
     */
    @Override
    public Video queryVideoById(String videoId) {
        return null;
    }


    /**
     * 保存视频
     *
     * @param video 视频实体类
     * @return
     */
    @Override
    public Boolean saveVideo(Video video) {
        //判断传过来的实体类的值是否有为空的，有空为true,"id",   "vid", "created"为排除属性
        boolean b = BeanUtil.isEmpty(video);
        if (b) {
            return false;
        }

        try {
            //有值，就生成还为空的属性
            video.setId(new ObjectId());
            //设置通过Redis自动增长设置不重复的vid
            video.setVid(idService.createId(IdType.VIDEO));
            //创建时间
            video.setCreated(System.currentTimeMillis());

            //添加到MongoDB中
            mongoTemplate.save(video);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 查询视频列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public List<Video> queryVideoList(Long userId, Integer page, Integer pageSize) {
        //去Redis中查询是否有推荐列表的vid数据
        String redisKey = "QUANZI_VIDEO_RECOMMEND_" + userId;
        String redisData = redisTemplatel.opsForValue().get(redisKey);
        if (redisData == null) {
            return null;
        }

        //根据","分割redisData,得到所有单独的推荐vid
        List<String> split = StrUtil.split(redisData, ',');

        //对split进行分页推荐,得到分页后的数据,糊涂工具
        int[] ints = PageUtil.transToStartEnd(page - 1, pageSize);
        //开始
        int start = ints[0];
        //得到最小的结束,防止数据超出如推荐列表只有5而size为10,
        int end = Math.min(ints[1], split.size());

        //通过循环得到这次查询的所有推荐列表vid数据
        List<Long> vidList = new ArrayList<>();
        for (int i = start; i < end; i++) {
            vidList.add(Long.valueOf(split.get(i)));
        }
        //判断推荐列表是否还有值,true为无值
        if (vidList.size() == 0) {
            //推荐列表没数据后查询数据库来获得数据
            //从MongoDB中查询数据需要从第一页开始查,而查询完推荐列表后的页码以及不是第一页了需要通过PageUtil获取前面的页数来相减
            int totalPage = PageUtil.totalPage(split.size(), pageSize);
            //从MongoDB中查询数据
            List<Video> videos = mongoTemplate.find(new Query()
                            .limit(pageSize)
                            .skip((long) (page - 1 - totalPage) * pageSize)
                            .with(Sort.by(Sort.Order.desc("created")))
                    , Video.class);
            return videos;
        } else {
            //根据推荐的vid来MongoDB查询数据,以及分好了页不需要再进行分页
            List<Video> videos = mongoTemplate.find(new Query(Criteria
                            .where("vid")
                            .in(vidList))
                            .with(Sort.by(Sort.Order.desc("created")))
                    , Video.class);
            return videos;
        }

    }

    /**
     * 根据userId查询数据
     *
     * @param userId 用户id
     * @return
     */
    @Override
    public Video queryVideoById(Long userId) {
        return mongoTemplate.findOne(new Query(Criteria.where("userId").is(userId)), Video.class);

    }

    /**
     * 添加关注信息到MongoDB
     * @param toUserid 被关注的用户
     * @param id 点击关注的用户
     * @return 是否保存成功
     */
    @Override
    public Boolean attention(String toUserid, Long id) {
        try {
            mongoTemplate.insert(new FollowUser(new ObjectId(),id,Long.valueOf(toUserid),System.currentTimeMillis()));
            return true;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 删除关注信息
     * @param toUserid 被关注的用户的id
     * @param id 用户id
     * @return 是否删除成功
     */
    @Override
    public Boolean unsubscribe(String toUserid, Long id) {
        try {
            mongoTemplate.remove(new Query(Criteria.where("followUserId").is(toUserid).and("userId").is(id)),FollowUser.class);
            return true;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return false;
    }
}
